//
//  NSObject+FPlugin.m
//  Foundation
//
//  Created by 三井 on 2019/10/21.
//

#import "NSObject+FPlugin.h"
#import "FPluginFakeArray.h"
#import "FPluginHost.h"
#import "FPlugin.h"
#import <objc/runtime.h>
#import "FPluginCenter.h"
#import "FPluginStore.h"
#import "NSObject+FPluginData.h"

static const void * kPluginHostKey = &kPluginHostKey;

@interface NSObject () <FPlugin>

@end
@implementation NSObject (FPlugin)

- (NSMutableArray *)plg_datas {
    return self.pluginHost.datas;
}

- (FPluginHost *)pluginHost {
    FPluginHost *host = objc_getAssociatedObject(self, &kPluginHostKey);
    if (!host) {
        host = [self hostFor:nil];
        objc_setAssociatedObject(self, &kPluginHostKey, host, OBJC_ASSOCIATION_RETAIN);
    }
    return host;
}

- (FPluginContext *)context {
    return self.pluginHost.context;
}

- (void)setPluginPriority:(NSArray<NSString *> *)pluginPriority {
    self.pluginHost.pluginPriority = pluginPriority;
}

- (NSArray<NSString *> *)pluginPriority {
    return self.pluginHost.pluginPriority;
}

- (BOOL)plg_beginUpdate { return YES; }
- (void)plg_endUpdate {}

- (NSInteger)plghost_load:(FPluginArg *)arg {
    arg.collectable = self;
    FPluginHost *host = [self pluginHost:arg];
    
    if (self.pluginPriority) {
        host.pluginPriority = self.pluginPriority;
    }
    
    return [host loadPlugins:arg];
}

- (void)plghost_refresh:(FPluginArg *)arg {
    FPluginHost *host = [self pluginHost:arg];
    [host refreshPlugins:arg];
}

- (void)plghost_unload {
    
}

- (FPluginHost *)hostFor:(FPluginArg *)arg {
    return [[FPluginHost alloc] initWithHost:arg.hostIdentifier];
}

- (FPluginHostProxy *)proxyFor:(FPluginArg *)arg {
    return nil;
}

- (FPluginFake *)fakeForIdentifier:(NSString *)identifier {
    return nil;
}

+ (instancetype)instanceForHost:(NSString *)hostIdentifier {
    for (FPluginHost *host in FPluginCenter.sharedInstance.pluginStore.hosts) {
        if ([host.hostIdentifier isEqualToString:hostIdentifier]) {
            for (id<FPlugin> plg in host.plugins) {
                if ([self isEqualPlugin:plg]) {
                    return plg;
                }
            }
        }
    }
    return nil;
}

#pragma mark - Private

- (FPluginHost *)pluginHost:(FPluginArg *)arg {
    FPluginHost *host = self.pluginHost;
    if (![host.hostIdentifier isEqualToString:arg.hostIdentifier]) {
        [host reloadWithHost:arg.hostIdentifier];
    }
    
    return host;
}
@end
